LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY table_test IS
	PORT
	(
		clk,reset	:	IN STD_LOGIC;
		current_desired_output, Table_to_Forwarding_Port	:	BUFFER STD_LOGIC_VECTOR (2 DOWNTO 0);
		dont_care	:	BUFFER STD_LOGIC;
		test_case_number,pass_count	:	OUT STD_LOGIC_VECTOR (9 downto 0);
		srcAddress,desAddress	:	BUFFER STD_LOGIC_VECTOR (47 downto 0);
		srcPort	:	BUFFER STD_LOGIC_VECTOR (1 downto 0);
		test_pass, result_active	:	OUT STD_LOGIC
	);
END table_test;

ARCHITECTURE arch OF table_test IS

COMPONENT table IS
    PORT (clock, reset, Forwarding_to_Table_ACK : IN STD_LOGIC;
          Forwarding_to_Table_srcPort : IN STD_LOGIC_VECTOR(1 downto 0);
          Forwarding_to_Table_srcAddress, Forwarding_to_Table_desAddress: IN STD_LOGIC_VECTOR(47 downto 0);
          Table_to_Forwarding_Port: OUT STD_LOGIC_VECTOR(2 downto 0);
          Table_to_Forwarding_ACK, Table_to_Forwarding_Valid  : OUT STD_LOGIC);
END COMPONENT;

COMPONENT decoder IS
	PORT
	(
		i	:	IN STD_LOGIC_VECTOR(127 DOWNTO 0);
		srcPort : OUT STD_LOGIC_VECTOR(1 downto 0);
        srcAddress, desAddress: OUT STD_LOGIC_VECTOR(47 downto 0);
        done	:	OUT STD_LOGIC
	);
END COMPONENT;

COMPONENT rom_128 IS
	PORT
	(
		address		: IN STD_LOGIC_VECTOR (9 DOWNTO 0);
		clock		: IN STD_LOGIC  := '1';
		q		: OUT STD_LOGIC_VECTOR (127 DOWNTO 0)
	);
END COMPONENT;

COMPONENT rom_4 IS
	PORT
	(
		address		: IN STD_LOGIC_VECTOR (9 DOWNTO 0);
		clock		: IN STD_LOGIC  := '1';
		q		: OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
	);
END COMPONENT;

COMPONENT pc IS
	PORT
	(
		aclr		: IN STD_LOGIC ;
		clk_en		: IN STD_LOGIC ;
		clock		: IN STD_LOGIC ;
		q		: OUT STD_LOGIC_VECTOR (9 DOWNTO 0)
	);
END COMPONENT;

TYPE state_type is (send_input,wait_for_output,show_result);

SIGNAL pc_clk, Forwarding_to_Table_ACK, Table_to_Forwarding_Valid, Table_to_Forwarding_ACK, done, test_pass_sig, result_active_sig	:	STD_LOGIC;
SIGNAL pc_addr	:	STD_LOGIC_VECTOR (9 DOWNTO 0);
SIGNAL current_input : STD_LOGIC_VECTOR (127 DOWNTO 0);
--SIGNAL srcPort : STD_LOGIC_VECTOR(1 downto 0);
--SIGNAL srcAddress, desAddress: STD_LOGIC_VECTOR(47 downto 0);
--SIGNAL current_desired_output, Table_to_Forwarding_Port	:	STD_LOGIC_VECTOR (2 DOWNTO 0);
SIGNAL q	:	STD_LOGIC_VECTOR (3 DOWNTO 0);
SIGNAL state,state_next: state_type;

BEGIN

pc_counter: pc PORT MAP(reset,'1',pc_clk,pc_addr);
test_case_number <= pc_addr;

inputs: rom_128 PORT MAP(pc_addr,clk,current_input);

outputs: rom_4 PORT MAP(pc_addr,clk,q);
current_desired_output <= q(2 DOWNTO 0);
dont_care <= q(3); 

decode: decoder PORT MAP(current_input,srcPort,srcAddress,desAddress,done);

t: table PORT MAP(clk,reset,Forwarding_to_Table_ACK,srcPort,
		srcAddress,desAddress,Table_to_Forwarding_Port,
		Table_to_Forwarding_ACK, Table_to_Forwarding_Valid);

process (clk,reset)
begin
 if (reset='1') then
  state <= send_input; 
elsif (rising_edge(clk)) then
  state <= state_next;   
end if;
end process;
	
process(state)
begin
	Forwarding_to_Table_ACK <= '0';
	test_pass_sig <= '0';
	result_active_sig <= '0';
	pc_clk <= '0';
	state_next <= state;
	case state is
		when send_input =>
			if done = '1' then
				state_next <= send_input;
			elsif Table_to_Forwarding_ACK = '1' then
				state_next <= wait_for_output;
			else
				Forwarding_to_Table_ACK <= '1';
			end if;
		when wait_for_output =>
			if Table_to_Forwarding_Valid = '1' then
				if (Table_to_Forwarding_Port = current_desired_output) or (dont_care = '1') then
					test_pass_sig <= '1';
				end if;	
				result_active_sig <= '1';
				state_next <= show_result;
			end if;
		when show_result =>
			state_next <= send_input;
			pc_clk <= '1';
	end case;
end process;

pass_counter: pc port map(reset,test_pass_sig AND result_active_sig,clk,pass_count);

result_active <= result_active_sig;
test_pass <= test_pass_sig;
END arch;